import { ref, toRaw } from 'vue'

import * as monaco from 'monaco-editor'

import jsonWorker from 'monaco-editor/esm/vs/language/json/json.worker?worker'
import cssWorker from 'monaco-editor/esm/vs/language/css/css.worker?worker'
import htmlWorker from 'monaco-editor/esm/vs/language/html/html.worker?worker'
import tsWorker from 'monaco-editor/esm/vs/language/typescript/ts.worker?worker'
import EditorWorker from 'monaco-editor/esm/vs/editor/editor.worker?worker'

import type { BwMonacoEditorProps, monacoEditorModel } from './model'

import { createSnippets } from './snippets'
import { createTips } from './tips'
import { createTypes } from './types'
import { createLanguages } from './languages'
import { createMenus } from './menus'
import { createCommands } from './commands'
import { getOptions } from './options'

export default class BwMonacoEditor {
  /** 当前语言 */
  curLanguage = ref<string>('typescript')

  /** 创建格式整理 */
  // createFormatter(curLanguage.value)

  /** 编辑器实例 */
  editor = ref<monaco.editor.IStandaloneCodeEditor>()

  /** 注销 */
  dispose = () => {
    if (this.editor.value) {
      toRaw(this.editor.value).dispose()
    }
  }

  /**
   * 创建Editor实例
   * params.domElement：dom元素
   * params.options：编辑器参数
   */
  create = (params: BwMonacoEditorProps) => {
    if (!params.domElement) return

    /** 注销原有实例 */
    this.dispose()

    //#region 参数处理
    if (!params.options) {
      params.options = {
        language: 'typescript',
      }
    } else if (params.options) {
      params.options.language = params.options.language ?? 'typescript'
      this.curLanguage.value = params.options.language ?? 'typescript'
    }
    //#endregion

    //#region 重构语言包
    self.MonacoEnvironment = {
      getWorker(_: string, label: string) {
        let _v: Worker | Promise<Worker> | undefined = undefined

        if (label === 'json') {
          _v = new jsonWorker()
        } else if (label === 'css' || label === 'scss' || label === 'less') {
          _v = new cssWorker()
        } else if (
          label === 'html' ||
          label === 'handlebars' ||
          label === 'razor'
        ) {
          _v = new htmlWorker()
        } else if (['typescript', 'javascript'].includes(label)) {
          _v = new tsWorker()
        } else {
          _v = new EditorWorker()
        }

        return _v
      },
    }
    //#endregion

    /** 创建代码提示 */
    createTips(this.curLanguage.value, params.tips)

    /** 创建代码片段 */
    createSnippets(this.curLanguage.value, params.snippets)

    /** 创建自定义类型 */
    createTypes(this.curLanguage.value, params.types)

    /** 语言初始 */
    createLanguages(this.curLanguage.value)

    /** 编辑器参数 */
    const curOptions: monacoEditorModel = getOptions(params.options)

    /** 创建编辑器 */
    this.editor.value = monaco.editor.create(params.domElement, curOptions)

    /** 创建菜单 */
    createMenus(this.editor.value, params.menus)

    /** 创建指令 */
    createCommands(this.editor.value, params.commands)

    return this.editor.value
  }
}
